/****************************************************************************
 *
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/


/**
 * @file
 *   @brief Map Tile Cache Worker Thread
 *
 *   @author Gus Grubba <gus@auterion.com>
 *
 */

#ifndef QGC_TILE_CACHE_WORKER_H
#define QGC_TILE_CACHE_WORKER_H

#include <QString>
#include <QThread>
#include <QQueue>
#include <QMutex>
#include <QWaitCondition>
#include <QMutexLocker>
#include <QtSql/QSqlDatabase>
#include <QHostInfo>


class QGCMapTask;
class QGCCachedTileSet;

/**
 * @brief 地图瓦片缓存工作线程类
 * 
 * QGCCacheWorker 是一个专门用于处理地图瓦片缓存操作的工作线程类，继承自 QThread。
 * 它负责执行各种与地图瓦片缓存相关的任务，如保存瓦片、获取瓦片、管理瓦片集合等。
 * 该类通过任务队列机制处理请求，确保数据库操作在独立线程中进行，避免阻塞UI线程。
 * 
 * 主要功能包括：
 * 1. 管理地图瓦片的缓存存储和检索
 * 2. 维护瓦片集合信息
 * 3. 处理瓦片下载列表和状态更新
 * 4. 执行缓存数据库的维护操作（如清理、重置等）
 * 5. 网络连接状态检测
 */
//-----------------------------------------------------------------------------
class QGCCacheWorker : public QThread
{
    Q_OBJECT
public:
    /**
     * @brief 构造函数
     * 初始化缓存工作线程对象的成员变量
     */
    QGCCacheWorker  ();
    
    /**
     * @brief 析构函数
     */
    ~QGCCacheWorker ();

    /**
     * @brief 退出工作线程
     * 中止正在进行的主机查找，清空任务队列并唤醒等待的线程
     */
    void    quit            ();
    
    /**
     * @brief 将任务添加到队列中
     * @param task 要执行的地图任务
     * @return 成功入队返回true，否则返回false
     */
    bool    enqueueTask     (QGCMapTask* task);
    
    /**
     * @brief 设置数据库文件路径
     * @param path 数据库文件的路径
     */
    void    setDatabaseFile (const QString& path);

protected:
    /**
     * @brief 线程执行入口函数
     * 线程启动后执行的主要函数，处理任务队列中的各项任务
     */
    void    run             ();

private slots:
    /**
     * @brief 主机查找完成槽函数
     * @param info 主机信息
     */
    void        _lookupReady            (QHostInfo info);

private:
    /**
     * @brief 执行任务
     * @param task 要执行的地图任务
     */
    void        _runTask                (QGCMapTask* task);

    /**
     * @brief 保存瓦片到缓存
     * @param mtask 地图任务
     */
    void        _saveTile               (QGCMapTask* mtask);
    
    /**
     * @brief 从缓存获取瓦片
     * @param mtask 地图任务
     */
    void        _getTile                (QGCMapTask* mtask);
    
    /**
     * @brief 获取所有瓦片集合
     * @param mtask 地图任务
     */
    void        _getTileSets            (QGCMapTask* mtask);
    
    /**
     * @brief 创建瓦片集合
     * @param mtask 地图任务
     */
    void        _createTileSet          (QGCMapTask* mtask);
    
    /**
     * @brief 获取瓦片下载列表
     * @param mtask 地图任务
     */
    void        _getTileDownloadList    (QGCMapTask* mtask);
    
    /**
     * @brief 更新瓦片下载状态
     * @param mtask 地图任务
     */
    void        _updateTileDownloadState(QGCMapTask* mtask);
    
    /**
     * @brief 删除瓦片集合
     * @param mtask 地图任务
     */
    void        _deleteTileSet          (QGCMapTask* mtask);
    
    /**
     * @brief 重命名瓦片集合
     * @param mtask 地图任务
     */
    void        _renameTileSet          (QGCMapTask* mtask);
    
    /**
     * @brief 重置缓存数据库
     * @param mtask 地图任务
     */
    void        _resetCacheDatabase     (QGCMapTask* mtask);
    
    /**
     * @brief 清理缓存
     * @param mtask 地图任务
     */
    void        _pruneCache             (QGCMapTask* mtask);
    
    /**
     * @brief 导出瓦片集合
     * @param mtask 地图任务
     */
    void        _exportSets             (QGCMapTask* mtask);
    
    /**
     * @brief 导入瓦片集合
     * @param mtask 地图任务
     */
    void        _importSets             (QGCMapTask* mtask);
    
    /**
     * @brief 测试任务
     * @param mtask 地图任务
     * @return 测试通过返回true，否则返回false
     */
    bool        _testTask               (QGCMapTask* mtask);
    
    /**
     * @brief 测试网络连接
     */
    void        _testInternet           ();
    
    /**
     * @brief 删除Bing空瓦片
     */
    void        _deleteBingNoTileTiles  ();

    /**
     * @brief 查找瓦片
     * @param hash 瓦片的哈希值
     * @return 瓦片ID，如果未找到返回0
     */
    quint64     _findTile               (const QString hash);
    
    /**
     * @brief 查找瓦片集合ID
     * @param name 瓦片集合名称
     * @param setID[out] 找到的瓦片集合ID
     * @return 找到返回true，否则返回false
     */
    bool        _findTileSetID          (const QString name, quint64& setID);
    
    /**
     * @brief 更新集合统计信息
     * @param set 瓦片集合对象
     */
    void        _updateSetTotals        (QGCCachedTileSet* set);
    
    /**
     * @brief 初始化数据库
     * @return 初始化成功返回true，否则返回false
     */
    bool        _init                   ();
    
    /**
     * @brief 连接数据库
     * @return 连接成功返回true，否则返回false
     */
    bool        _connectDB              ();
    
    /**
     * @brief 创建数据库
     * @param db 数据库对象
     * @param createDefault 是否创建默认集合
     * @return 创建成功返回true，否则返回false
     */
    bool        _createDB               (QSqlDatabase& db, bool createDefault = true);
    
    /**
     * @brief 断开数据库连接
     */
    void        _disconnectDB           ();
    
    /**
     * @brief 获取默认瓦片集合
     * @return 默认瓦片集合ID
     */
    quint64     _getDefaultTileSet      ();
    
    /**
     * @brief 更新统计信息
     */
    void        _updateTotals           ();
    
    /**
     * @brief 删除瓦片集合
     * @param id 要删除的瓦片集合ID
     */
    void        _deleteTileSet          (qulonglong id);

signals:
    /**
     * @brief 更新统计信息信号
     * @param totaltiles 总瓦片数
     * @param totalsize 总大小
     * @param defaulttiles 默认集合瓦片数
     * @param defaultsize 默认集合大小
     */
    void        updateTotals            (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize);
    
    /**
     * @brief 网络状态信号
     * @param active 网络是否可用
     */
    void        internetStatus          (bool active);

private:
    QQueue<QGCMapTask*>             _taskQueue;          ///< 任务队列，存储待处理的地图任务
    QMutex                          _taskQueueMutex;     ///< 任务队列互斥锁，保证线程安全
    QWaitCondition                  _waitc;              ///< 等待条件变量，用于线程间同步
    QString                         _databasePath;       ///< 数据库文件路径
    QScopedPointer<QSqlDatabase>    _db;                 ///< 数据库连接对象
    std::atomic_bool                _valid;              ///< 数据库连接是否有效
    bool                            _failed;             ///< 初始化是否失败
    quint64                         _defaultSet;         ///< 默认瓦片集合ID
    quint64                         _totalSize;          ///< 缓存总大小
    quint32                         _totalCount;         ///< 缓存瓦片总数
    quint64                         _defaultSize;        ///< 默认集合大小
    quint32                         _defaultCount;       ///< 默认集合瓦片数
    time_t                          _lastUpdate;         ///< 上次更新时间
    int                             _updateTimeout;      ///< 更新超时时间
    int                             _hostLookupID;       ///< 主机查找ID
};

#endif // QGC_TILE_CACHE_WORKER_H